/*
 * optWFQueue.h
 * A wait free queue
 * @author Hani shubin
 */
#ifndef OPT_WFQUEUE_
#define OPT_WFQUEUE_

#include "Node.h"

/*
 * USE_HP is a compilation flag that indicates whether the queue uses the HP
 * method or not.
 */
#ifdef USE_HP
#include "MemoryManager.h"
#endif

/**
 * A state of a thread:
 * 	phase: it's phase
 *  pending: if it's pending
 *  enquueOp: true of it's current operation is enqueue
 *  node: the node that is enqueued/dequeued
 */
typedef struct OpDesc_t {
	long phase;
	void* data;
} OpDesc;

/**
 * Queue data.
 * 		head- the head of the queue
 * 		tail- the tail of the queue
 * 		states- an array of OpDesc for each thread
 * 		numOfThreads- number of threads that uses the queue
 * 		memoryManager- the MemoryManager of the queue
 */
typedef struct optWFQueue_t{
	Node* head;
	Node* tail;
	OpDesc* states;
	long long* nextToHelp;
	long maxPhaseCnt;
	unsigned int numOfThreads;
#ifdef USE_HP
	MemoryManager* memoryManager;
#endif
}optWFQueue;

/**
 * Get a optWFQueue (c'tor).
 * Input: numOfThreads that will use the optWFQueue.
 * Output: a new initialized optWFQueue.
 */
inline optWFQueue* getQueue(unsigned int numOfThreads);

/**
 * Delete a optWFQueue (d'tor).
 * Input: a optWFQueue to be deleted.
 * Assumption: 	This function must be called after all threads have finished
 * 				running.
 */
inline void deleteQueue(optWFQueue* queue);

/**
 * Insert a value to the queue.
 * Input: 	queue- the queue where the value should be inserted
 * 			myTid- the tid of the inserting thread
 * 			value- the value to be inserted
 */
inline void enq(optWFQueue* queue, long long myTid, int value);

/**
 * Remove a value from the queue.
 * Input: 	queue- the queue from where to take a value
 * 			myTid- the tid of the removing thread
 * Output: 	the value that was taken from the queue
 * 			or -1 if the queue is empty
 */
int deq(optWFQueue* queue, long long myTid);

/**
 * Print queue nodes
 */
inline void printQueue(optWFQueue* queue);
/**
 * Print queue size
 */
inline void printQueueSize(optWFQueue* queue);


#endif /* OPT_WFQUEUE_ */
